
/*
    Software License

    Copyright (C) 2021-05-24  Xoronos

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, version 3.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/

/*
    Liabilities

    The software is provided "AS IS" without any warranty of any kind, either expressed,
    implied, or statutory, including, but not limited to, any warranty that the software
    will conform to specifications, any implied warranties of merchantability, fitness
    for a particular purpose, and freedom from infringement, and any warranty that the
    documentation will conform to the software, or any warranty that the software will
    be error free.

    In no event shall Xoronos be liable for any damages, including, but not limited to,
    direct, indirect, special or consequential damages, arising out of, resulting from,
    or in any way connected with this software, whether or not based upon warranty,
    contract, tort, or otherwise, whether or not injury was sustained by persons or
    property or otherwise, and whether or not loss was sustained from, or arose out of
    the results of, or use of, the software or services provided hereunder.

    To request the provided software under a different license you can contact us at
    support@xoronos.com
*/

#include "xrn_encoder.h"

int xrn_compare_encoding_parameters( xrn_encoding_param_t enc_param1, xrn_encoding_param_t enc_param2
 )
{
    XPRINT_DEB(  );

    int ret, i, error;

    ret = xrn_check_encoding_parameters( enc_param1 );
    if ( ret != XSUCCESS ) {

        XPRINT_ERR( 2154, XERR_GENERAL_MSG );
        return ret;

    }

    ret = xrn_check_encoding_parameters( enc_param2 );
    if ( ret != XSUCCESS ) {

        XPRINT_ERR( 2155, XERR_GENERAL_MSG );
        return ret;

    }

    error = 0;
    for ( i = 0; i < 256; i++ ) {
        error = error || ( enc_param1.table[i] != enc_param2.table[i] );
    }

    for ( i = 0; i < 4; i++ ) {
        error = error || ( enc_param1.prng_state[i] != enc_param2.prng_state[i] );
    }

    if ( error ) {
        return XNOT_EQUAL;
    }

    return XEQUAL;

}

int xrn_check_encoding_settings( xrn_encoding_settings_t enc_settings
 )
{
    XPRINT_DEB(  );

    int error;

    // check mode

    error = 1;
    if ( ( enc_settings.mode == no_encoding ) ||
         ( enc_settings.mode == std_parameters ) ||
         ( enc_settings.mode == xrn_parameters ) ||
         ( enc_settings.mode == std_parameters_plus_file ) ||
         ( enc_settings.mode == xrn_parameters_plus_file ) ||
         ( enc_settings.mode == std_parameters_plus_password ) ||
         ( enc_settings.mode == xrn_parameters_plus_password ) ) {
        error = 0;
    }

    if ( error == 1 ) {
        XPRINT_ERR( 2226, XERR_ENC_STRUCTURES_MSG );
        return XERR_ENC_STRUCTURES;
    }

    if ( ( ( enc_settings.mode == std_parameters_plus_file ) ||
           ( enc_settings.mode == xrn_parameters_plus_file ) ) &&
         ( enc_settings.initialization_file_fp == NULL ) ) {
        XPRINT_ERR( 703, XERR_ENC_STRUCTURES_MSG );
        return XERR_ENC_STRUCTURES;
    }

    // check mode

    error = 1;
    if ( ( enc_settings.check_mode == xrn_automatic ) || ( enc_settings.check_mode == xrn_manual ) ) {
        error = 0;
    }

    if ( error == 1 ) {
        XPRINT_ERR( 2227, XERR_ENC_STRUCTURES_MSG );
        return XERR_ENC_STRUCTURES;
    }

    if ( ( enc_settings.mode == std_parameters_plus_password ) ||
         ( enc_settings.mode == xrn_parameters_plus_password ) ) {
        if ( enc_settings.password_length > XRN_ENC_PASS_BUFF_SIZE ) {
            XPRINT_ERR( 2233, XERR_ENC_STRUCTURES_MSG );
            return XERR_ENC_STRUCTURES;
        }

    }

    if ( ( enc_settings.mode == xrn_parameters ) || ( enc_settings.mode == xrn_parameters_plus_password ) ) {
        if ( enc_settings.encoding_parameters_fp == NULL ) {
            XPRINT_ERR( 2228, XERR_ENC_STRUCTURES_MSG );
            return XERR_ENC_STRUCTURES;
        }

    }

    if ( enc_settings.check_running_error_en == 1 ) {
        if ( ( enc_settings.max_consecutives_01s_threshold_error <
               enc_settings.max_consecutives_01s_threshold_warning ) ||
             ( ( enc_settings.max_consecutives_01s_threshold_error <
                 XRN_ENC_MAX_CONS_01_ERR_TH - XRN_ENC_MAX_CONS_01_ERR_TH / 4 ) ) ||
             ( ( enc_settings.max_consecutives_01s_threshold_error >
                 XRN_ENC_MAX_CONS_01_ERR_TH + XRN_ENC_MAX_CONS_01_ERR_TH / 4 ) ) ||
             ( ( enc_settings.max_consecutives_01s_threshold_warning <
                 XRN_ENC_MAX_CONS_01_WAR_TH - XRN_ENC_MAX_CONS_01_WAR_TH / 4 ) ) ||
             ( ( enc_settings.max_consecutives_01s_threshold_warning >
                 XRN_ENC_MAX_CONS_01_WAR_TH + XRN_ENC_MAX_CONS_01_WAR_TH / 4 ) )
             ) {
            XPRINT_ERR( 51, XERR_ENC_STRUCTURES_MSG );
            return XERR_ENC_STRUCTURES;
        }

    }

    if ( enc_settings.check_disparity_error_en == 1 ) {
        if ( ( enc_settings.max_number_of_01s_threshold_error <
               enc_settings.max_number_of_01s_threshold_warning ) ||
             ( ( enc_settings.max_number_of_01s_threshold_error <
                 XRN_ENC_MAX_AVG_01_ERR_TH - XRN_ENC_MAX_AVG_01_ERR_TH / 4 ) ) ||
             ( ( enc_settings.max_number_of_01s_threshold_error >
                 XRN_ENC_MAX_AVG_01_ERR_TH + XRN_ENC_MAX_AVG_01_ERR_TH / 4 ) ) ||
             ( ( enc_settings.max_number_of_01s_threshold_warning <
                 XRN_ENC_MAX_AVG_01_WAR_TH - XRN_ENC_MAX_AVG_01_WAR_TH / 4 ) ) ||
             ( ( enc_settings.max_number_of_01s_threshold_warning >
                 XRN_ENC_MAX_AVG_01_WAR_TH + XRN_ENC_MAX_AVG_01_WAR_TH / 4 ) )
             ) {

            XPRINT_ERR( 52, XERR_ENC_STRUCTURES_MSG );
            return XERR_ENC_STRUCTURES;
        }

    }

    return XSUCCESS;
}

int xrn_check_encoding_interface( xrn_interface_settings_t enc_interface
 )
{
    XPRINT_DEB(  );

    int ret;

    ret = xrn_check_encoding_settings( enc_interface.i_settings );

    if ( ret != XSUCCESS ) {
        XPRINT_ERR( 2229, XERR_ENC_STRUCTURES_MSG );
        return XERR_ENC_STRUCTURES;
    }

    ret = xrn_check_encoding_settings( enc_interface.o_settings );
    if ( ret != XSUCCESS ) {
        XPRINT_ERR( 2230, XERR_ENC_STRUCTURES_MSG );
        return XERR_ENC_STRUCTURES;
    }

    return XSUCCESS;
}

int xrn_check_encoding_parameters( xrn_encoding_param_t enc_param
 )
{
    XPRINT_DEB(  );

    int i, j, error, all_zero;

    error = 1;

    all_zero = enc_param.table[0] == 0;

    for ( i = 1; i < 256; i++ ) {

        if ( enc_param.table[i] == enc_param.table[0] ) {
            error = 0;
        }

        if ( enc_param.table[i] == 0 ) {
            all_zero++;
        }

    }

    for ( i = 1; i < 256; i++ ) {
        for ( j = 1; j < 256; j++ ) {
            if ( i != j ) {
                if ( enc_param.table[i] == enc_param.table[j] ) {
                    error = 1;
                }

            }

        }

    }

    if ( ( error ) && ( all_zero != 256 ) ) {

        XPRINT_ERR( 2231, XERR_ENC_STRUCTURES_MSG );
        return XERR_ENC_STRUCTURES;
    }

    if ( ( enc_param.prng_state[0] == enc_param.prng_state[1] ) &&
         ( enc_param.prng_state[2] == enc_param.prng_state[3] ) &&
         ( enc_param.prng_state[0] == enc_param.prng_state[3] ) &&
         ( enc_param.prng_state[0] == 0 ) && ( all_zero != 256 )
         ) {
        XPRINT_ERR( 2232, XERR_ENC_STRUCTURES_MSG );
        return XERR_ENC_STRUCTURES;

    }

    return XSUCCESS;

}

// uint64_t rotl( uint64_t x, int k) {
//    return (x << k) | (x >> (64 - k));
// }

// uint64_t xorshiro256(uint64_t * s) {
//
//   uint64_t result = s[0] + s[3];
//   uint64_t t = s[1] << 17;
//   
//   s[2] ^= s[0];
//   s[3] ^= s[1];
//   s[1] ^= s[2];
//   s[0] ^= s[3];
//   
//   s[2] ^= t;
//   
//   s[3] = rotl(s[3], 45);
//   
//   return result;
// }

int xrn_encode( xrn_encoding_param_t * encoding_param,
                uint8_t plain_message[],
                uint8_t enc_message[], uint64_t message_length, xrn_encoding_tmp_param_t * tmp
 )
{
    XPRINT_DEB(  );

    if ( ( encoding_param == NULL ) || ( enc_message == NULL ) || ( plain_message == NULL )
         || ( tmp == NULL ) ) {
        XPRINT_ERR( 2156, XERR_NULL_MSG );
        return ( XERR_NULL );
    }

    tmp->final_ret = XSUCCESS;

    for ( tmp->i = 0; tmp->i < message_length; tmp->i++ ) {

        tmp->t = encoding_param->prng_state[1] << 17;
        encoding_param->prng_state[2] ^= encoding_param->prng_state[0];
        encoding_param->prng_state[3] ^= encoding_param->prng_state[1];
        encoding_param->prng_state[1] ^= encoding_param->prng_state[2];
        encoding_param->prng_state[0] ^= encoding_param->prng_state[3];
        encoding_param->prng_state[2] ^= tmp->t;
        encoding_param->prng_state[3] =
            ( encoding_param->prng_state[3] << 45 ) | ( encoding_param->prng_state[3] >> 19 );

        tmp->pseudo_random_seed = ( ( uint8_t * ) & encoding_param->prng_state[0] )[0];
        tmp->hidden_index_prng = encoding_param->table[tmp->pseudo_random_seed];
        tmp->exposed_data_prng = encoding_param->table[tmp->hidden_index_prng];

        tmp->hidden_index_input = encoding_param->table[plain_message[tmp->i]];
        tmp->hidden_data_input = encoding_param->table[tmp->hidden_index_input];

        // calculate output
        enc_message[tmp->i] = tmp->exposed_data_prng ^ plain_message[tmp->i];

        // permute table
        encoding_param->table[0] = tmp->hidden_index_prng;
        encoding_param->table[tmp->hidden_index_input] = tmp->exposed_data_prng;
        encoding_param->table[tmp->hidden_index_prng] = tmp->hidden_data_input;

        // probabilistic checks
        if ( ( encoding_param->prob_checks.check_running_error_en == 1 )
             || ( encoding_param->prob_checks.check_disparity_error_en == 1 ) ) {
            tmp->ret = xrn_check_randomness( enc_message[tmp->i], encoding_param, tmp );
            tmp->final_ret = xrn_store_warnings_in_return_value( tmp->ret, tmp->final_ret );
            if ( tmp->final_ret == XERR_GENERAL ) {
                XPRINT_ERR( 2157, XERR_GENERAL_MSG );
                return ( tmp->ret );
            }

        }

    }

    return XSUCCESS;

}

int xrn_decode( xrn_encoding_param_t * encoding_param,
                uint8_t enc_message[],
                uint8_t plain_message[], uint64_t message_length, xrn_encoding_tmp_param_t * tmp
 )
{
    XPRINT_DEB(  );

    if ( ( enc_message == NULL ) || ( plain_message == NULL ) || ( encoding_param == NULL )
         || ( tmp == NULL ) ) {
        XPRINT_ERR( 2158, XERR_NULL_MSG );
        return ( XERR_NULL );
    }

    tmp->final_ret = XSUCCESS;

    for ( tmp->i = 0; tmp->i < message_length; tmp->i++ ) {

        // probabilistic checks
        if ( ( encoding_param->prob_checks.check_running_error_en == 1 )
             || ( encoding_param->prob_checks.check_disparity_error_en == 1 ) ) {
            tmp->ret = xrn_check_randomness( enc_message[tmp->i], encoding_param, tmp );
            tmp->final_ret = xrn_store_warnings_in_return_value( tmp->ret, tmp->final_ret );
            if ( tmp->final_ret == XERR_GENERAL ) {
                XPRINT_ERR( 2159, XERR_GENERAL_MSG );
                return ( tmp->ret );
            }

        }

        tmp->t = encoding_param->prng_state[1] << 17;
        encoding_param->prng_state[2] ^= encoding_param->prng_state[0];
        encoding_param->prng_state[3] ^= encoding_param->prng_state[1];
        encoding_param->prng_state[1] ^= encoding_param->prng_state[2];
        encoding_param->prng_state[0] ^= encoding_param->prng_state[3];
        encoding_param->prng_state[2] ^= tmp->t;
        encoding_param->prng_state[3] =
            ( encoding_param->prng_state[3] << 45 ) | ( encoding_param->prng_state[3] >> 19 );

        tmp->pseudo_random_seed = ( ( uint8_t * ) & encoding_param->prng_state[0] )[0];
        tmp->hidden_index_prng = encoding_param->table[tmp->pseudo_random_seed];
        tmp->exposed_data_prng = encoding_param->table[tmp->hidden_index_prng];
        plain_message[tmp->i] = tmp->exposed_data_prng ^ enc_message[tmp->i];

        // permute table
        tmp->hidden_index_input = encoding_param->table[plain_message[tmp->i]];
        tmp->hidden_data_input = encoding_param->table[tmp->hidden_index_input];

        encoding_param->table[0] = tmp->hidden_index_prng;
        encoding_param->table[tmp->hidden_index_input] = tmp->exposed_data_prng;
        encoding_param->table[tmp->hidden_index_prng] = tmp->hidden_data_input;

    }

    return XSUCCESS;

}

int xrn_initialize_encoding_interface( xrn_encoding_interface_t * encoding_interface, xrn_interface_settings_t encoding_interface_settings
 )
{
    XPRINT_DEB(  );

    int i;
    int ret;
    int final_ret;
    xrn_encoding_interface_t encoding_interface_local;

    if ( encoding_interface == NULL ) {
        XPRINT_ERR( 2160, XERR_NULL_MSG );
        return ( XERR_NULL );
    }

    for ( i = 0; i < sizeof( encoding_interface_local ); i++ ) {
        ( ( uint8_t * ) & encoding_interface_local )[i] = 0;
    }

    final_ret = XSUCCESS;

    ret = xrn_check_encoding_settings( encoding_interface_settings.i_settings );
    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 2161, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_check_encoding_settings( encoding_interface_settings.o_settings );
    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 2162, XERR_GENERAL_MSG );
        return ret;
    }

    ret =
        xrn_initialize_encoding_parameters( &encoding_interface_local.i_encoding_param,
                                            encoding_interface_settings.i_settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 2163, XERR_GENERAL_MSG );
        return ( ret );
    }

    ret = xrn_check_encoding_parameters( encoding_interface_local.i_encoding_param );
    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 2164, XERR_GENERAL_MSG );
        return ( ret );
    }

    ret =
        xrn_initialize_encoding_parameters( &encoding_interface_local.o_encoding_param,
                                            encoding_interface_settings.o_settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 2165, XERR_GENERAL_MSG );
        return ( ret );
    }

    ret = xrn_check_encoding_parameters( encoding_interface_local.o_encoding_param );
    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 2166, XERR_GENERAL_MSG );
        return ( ret );
    }

    *encoding_interface = encoding_interface_local;
    return XSUCCESS;

}

int xrn_initialize_encoding_parameters( xrn_encoding_param_t * encoding_param, xrn_encoding_settings_t encoding_settings
 )
{
    XPRINT_DEB(  );

    int i, ret, final_ret;
    xrn_encoding_param_t local_param;
    xrn_encoding_tmp_param_t tmp;

    if ( encoding_param == NULL ) {
        XPRINT_ERR( 2167, XERR_NULL_MSG );
        return ( XERR_NULL );
    }

    final_ret = XSUCCESS;

    ret = xrn_check_encoding_settings( encoding_settings );
    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 2168, XERR_GENERAL_MSG );
        return ret;
    }

    for ( i = 0; i < sizeof( tmp ); i++ ) {
        ( ( uint8_t * ) & tmp )[i] = 0;
    }

    for ( i = 0; i < sizeof( local_param ); i++ ) {
        ( ( uint8_t * ) & local_param )[i] = 0;
    }

    local_param.prob_checks.buffer_full = 0;
    local_param.prob_checks.index = 0;

    if ( encoding_settings.check_mode == xrn_automatic ) {
        if ( encoding_settings.mode == no_encoding ) {
            local_param.prob_checks.check_running_error_en = 0;
            local_param.prob_checks.check_disparity_error_en = 0;
        } else {
            local_param.prob_checks.check_running_error_en = 1;
            local_param.prob_checks.check_disparity_error_en = 1;
        }

        local_param.prob_checks.max_consecutives_01s_threshold_error = XRN_ENC_MAX_CONS_01_ERR_TH;
        local_param.prob_checks.max_consecutives_01s_threshold_warning = XRN_ENC_MAX_CONS_01_WAR_TH;
        local_param.prob_checks.max_number_of_01s_threshold_error = XRN_ENC_MAX_AVG_01_ERR_TH;
        local_param.prob_checks.max_number_of_01s_threshold_warning = XRN_ENC_MAX_AVG_01_WAR_TH;

    } else if ( encoding_settings.check_mode == xrn_manual ) {

        local_param.prob_checks.check_running_error_en = encoding_settings.check_running_error_en;
        local_param.prob_checks.check_disparity_error_en = encoding_settings.check_disparity_error_en;
        local_param.prob_checks.max_consecutives_01s_threshold_error =
            encoding_settings.max_consecutives_01s_threshold_error;
        local_param.prob_checks.max_consecutives_01s_threshold_warning =
            encoding_settings.max_consecutives_01s_threshold_warning;
        local_param.prob_checks.max_number_of_01s_threshold_error =
            encoding_settings.max_number_of_01s_threshold_error;
        local_param.prob_checks.max_number_of_01s_threshold_warning =
            encoding_settings.max_number_of_01s_threshold_warning;

    } else {

        XPRINT_ERR( 2169, XERR_TYPE_MSG );
        return XERR_TYPE;

    }

    if ( ( encoding_settings.mode == std_parameters )
         || ( encoding_settings.mode == std_parameters_plus_password ) ) {

        for ( i = 0; i < 256; i++ ) {
            local_param.table[i] = STD_ENC_PARAM_TABLE[i];
        }

        for ( i = 0; i < 8; i++ ) {
            ( ( uint32_t * ) & local_param.prng_state )[i] = STD_ENC_PARAM_CNT[i];
        }

        ret = xrn_check_encoding_parameters( local_param );
        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 2250, XERR_GENERAL_MSG );
            return ( ret );
        }

    } else if ( ( encoding_settings.mode == xrn_parameters )
                || ( encoding_settings.mode == xrn_parameters_plus_password ) ) {

        if ( encoding_settings.encoding_parameters_fp == NULL ) {
            XPRINT_ERR( 2170, XERR_NULL_MSG );
            return XERR_NULL;
        }

        ret = xrn_load_encoder_parameters( &local_param, encoding_settings.encoding_parameters_fp );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 2171, XERR_GENERAL_MSG );
            return ret;
        }

    }

    if ( ( encoding_settings.mode == xrn_parameters_plus_password )
         || ( encoding_settings.mode == std_parameters_plus_password ) ) {

        ret =
            xrn_permute_encoding_param_with_pass( local_param, ( uint8_t * ) encoding_settings.password,
                                                  encoding_settings.password_length, &local_param );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 616, XERR_GENERAL_MSG );
            return ret;
        }

    }

    if ( ( encoding_settings.mode == xrn_parameters_plus_file )
         || ( encoding_settings.mode == std_parameters_plus_file ) ) {

        ret =
            xrn_permute_encoding_param_with_file( local_param, encoding_settings.initialization_file_fp,
                                                  &local_param );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 750, XERR_GENERAL_MSG );
            return ret;
        }

    }

    if ( encoding_settings.mode == no_encoding ) {

        for ( i = 0; i < 256; i++ ) {
            local_param.table[i] = 0;
        }

        for ( i = 0; i < 8; i++ ) {
            ( ( uint32_t * ) & local_param.prng_state )[i] = 0;
        }

    }

    ret = xrn_check_encoding_parameters( local_param );
    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 2174, XERR_GENERAL_MSG );
        return ( ret );
    }

    *encoding_param = local_param;

    return XSUCCESS;

}

int xrn_dump_encoder_parameters_wrapper( xrn_encoding_settings_t encoding_settings, FILE * fp
 )
{

    XPRINT_DEB(  );
    xrn_encoding_param_t param;
    int ret;

    if ( fp == NULL ) {
        XPRINT_ERR( 1181, XERR_NULL_MSG );
        return XERR_NULL;
    }

    ret = xrn_check_encoding_settings( encoding_settings );
    if ( ret != XSUCCESS ) {
        XPRINT_ERR( 1184, XERR_GENERAL_MSG );
        return XERR_GENERAL;
    }

    if ( ( encoding_settings.mode == no_encoding ) ||
         ( encoding_settings.mode == std_parameters ) || ( encoding_settings.mode == xrn_parameters ) ) {
        XPRINT_ERR( 1185, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    ret = xrn_initialize_encoding_parameters( &param, encoding_settings );
    if ( ret != XSUCCESS ) {
        XPRINT_ERR( 1186, XERR_GENERAL_MSG );
        return XERR_GENERAL;
    }

    ret = xrn_dump_encoder_parameters( param, fp );
    if ( ret != XSUCCESS ) {
        XPRINT_ERR( 1187, XERR_GENERAL_MSG );
        return XERR_GENERAL;
    }

    return XSUCCESS;

}

int xrn_dump_encoder_parameters( xrn_encoding_param_t param, FILE * fp
 )
{
    XPRINT_DEB(  );
    uint32_t crc32;
    uint16_t rnd_padding;
    uint8_t rnd_byte;
    uint32_t magic_num;
    xrn_encoding_param_t rnd_param, rnd_param_perm;
    int i;

    uint16_t permutations[XRN_ENCODING_PERMUTATION_LEN] = XRN_ENCODING_PERMUTATION;

    if ( fp == NULL ) {
        XPRINT_ERR( 116, XERR_NULL_MSG );
        return XERR_NULL;
    }

    crc32 = 0xffffffff;
    magic_num = XRN_ENC_MAGIC_NUM;

    xrn_crc32( ( uint8_t * ) & magic_num, sizeof( uint32_t ), &crc32 );
    xrn_crc32( ( uint8_t * ) & param.table[0], sizeof( uint8_t ) * 256, &crc32 );
    xrn_crc32( ( uint8_t * ) & param.prng_state[0], sizeof( uint64_t ) * 1, &crc32 );
    xrn_crc32( ( uint8_t * ) & param.prng_state[1], sizeof( uint64_t ) * 1, &crc32 );
    xrn_crc32( ( uint8_t * ) & param.prng_state[2], sizeof( uint64_t ) * 1, &crc32 );
    xrn_crc32( ( uint8_t * ) & param.prng_state[3], sizeof( uint64_t ) * 1, &crc32 );

    if ( XSUCCESS != get_random_bytes( ( uint8_t * ) & rnd_param.table[0], XRN_ENCODING_PERMUTATION_LEN ) ) {
        XPRINT_ERR( 606, XERR_IO_MSG );
        return XERR_IO;
    }

    // permute bytes
    for ( i = 0; i < XRN_ENCODING_PERMUTATION_LEN; i++ ) {
        ( ( uint8_t * ) & rnd_param_perm.table[0] )[permutations[i]] =
            ( ( uint8_t * ) & rnd_param.table[0] )[i];
    }

    // reassign magic number with the crc of the original encoding paramether
    magic_num = crc32;

    if ( 1 != fwrite( &magic_num, sizeof( uint32_t ), 1, fp ) ) {
        XPRINT_ERR( 2176, XERR_IO_MSG );
        return XERR_IO;
    }

    // write encrypted encoding param
    for ( i = 0; i < 256; i++ ) {

        // encript encoding param
        param.table[i] = param.table[i] ^ rnd_param_perm.table[i];

        // write encoding param
        if ( 1 != fwrite( &param.table[i], sizeof( uint8_t ), 1, fp ) ) {
            XPRINT_ERR( 2177, XERR_IO_MSG );
            return XERR_IO;
        }

    }

    for ( i = 0; i < 4; i++ ) {
        // encript encoding param
        param.prng_state[i] = param.prng_state[i] ^ rnd_param_perm.prng_state[i];

        // write encoding param
        if ( 1 != fwrite( &param.prng_state[i], sizeof( uint64_t ), 1, fp ) ) {
            XPRINT_ERR( 2178, XERR_IO_MSG );
            return XERR_IO;
        }

    }

    // write random encoding param
    for ( i = 0; i < 256; i++ ) {

        if ( 1 != fwrite( &rnd_param.table[i], sizeof( uint8_t ), 1, fp ) ) {
            XPRINT_ERR( 607, XERR_IO_MSG );
            return XERR_IO;
        }

    }

    for ( i = 0; i < 4; i++ ) {

        if ( 1 != fwrite( &rnd_param.prng_state[i], sizeof( uint64_t ), 1, fp ) ) {
            XPRINT_ERR( 612, XERR_IO_MSG );
            return XERR_IO;
        }

    }

    // write random lenght padding to hide the type

    if ( XSUCCESS != get_random_bytes( ( uint8_t * ) & rnd_padding, 2 ) ) {
        XPRINT_ERR( 605, XERR_IO_MSG );
        return XERR_IO;
    }

    for ( i = 0; i < rnd_padding; i++ ) {

        if ( XSUCCESS != get_random_bytes( ( uint8_t * ) & rnd_byte, 1 ) ) {
            XPRINT_ERR( 618, XERR_IO_MSG );
            return XERR_IO;
        }

        if ( 1 != fwrite( &rnd_byte, sizeof( uint8_t ), 1, fp ) ) {
            XPRINT_ERR( 619, XERR_IO_MSG );
            return XERR_IO;
        }

    }

    return XSUCCESS;

}

int xrn_load_encoder_parameters( xrn_encoding_param_t * param, FILE * fp
 )
{
    XPRINT_DEB(  );
    int i, ret, final_ret;
    uint32_t crc32;
    uint32_t magic_num, magic_num_tmp;
    xrn_encoding_param_t local_param;
    xrn_encoding_param_t rnd_param;
    xrn_encoding_param_t rnd_param_perm;

    uint16_t permutations[XRN_ENCODING_PERMUTATION_LEN] = XRN_ENCODING_PERMUTATION;

    if ( ( param == NULL ) || ( fp == NULL ) ) {
        XPRINT_ERR( 117, XERR_NULL_MSG );
        return XERR_NULL;
    }

    rewind( fp );

    if ( 1 != fread( &magic_num, sizeof( uint32_t ), 1, fp ) ) {
        XPRINT_ERR( 2180, XERR_IO_MSG );
        return XERR_IO;
    }

    for ( i = 0; i < sizeof( local_param ); i++ ) {
        ( ( uint8_t * ) & local_param )[i] = 0;
    }

    final_ret = XSUCCESS;

    // get encrypted encoding param
    for ( i = 0; i < 256; i++ ) {

        if ( 1 != fread( &local_param.table[i], sizeof( uint8_t ), 1, fp ) ) {
            XPRINT_ERR( 2181, XERR_IO_MSG );
            return XERR_IO;
        }

    }

    for ( i = 0; i < 4; i++ ) {
        if ( 1 != fread( &local_param.prng_state[i], sizeof( uint64_t ), 1, fp ) ) {
            XPRINT_ERR( 2182, XERR_IO_MSG );
            return XERR_IO;

        }

    }

    // get random encoding param
    for ( i = 0; i < 256; i++ ) {

        if ( 1 != fread( &rnd_param.table[i], sizeof( uint8_t ), 1, fp ) ) {
            XPRINT_ERR( 614, XERR_IO_MSG );
            return XERR_IO;
        }

    }

    for ( i = 0; i < 4; i++ ) {
        if ( 1 != fread( &rnd_param.prng_state[i], sizeof( uint64_t ), 1, fp ) ) {
            XPRINT_ERR( 617, XERR_IO_MSG );
            return XERR_IO;

        }

    }

    // permute bytes
    for ( i = 0; i < XRN_ENCODING_PERMUTATION_LEN; i++ ) {
        ( ( uint8_t * ) & rnd_param_perm.table[0] )[permutations[i]] =
            ( ( uint8_t * ) & rnd_param.table[0] )[i];
    }

    // decrypt encoding param
    for ( i = 0; i < 256; i++ ) {
        local_param.table[i] = local_param.table[i] ^ rnd_param_perm.table[i];

    }

    for ( i = 0; i < 4; i++ ) {
        local_param.prng_state[i] = local_param.prng_state[i] ^ rnd_param_perm.prng_state[i];

    }

    crc32 = 0xffffffff;
    magic_num_tmp = XRN_ENC_MAGIC_NUM;
    xrn_crc32( ( uint8_t * ) & magic_num_tmp, sizeof( uint32_t ), &crc32 );
    xrn_crc32( ( uint8_t * ) & local_param.table[0], sizeof( uint8_t ) * 256, &crc32 );
    xrn_crc32( ( uint8_t * ) & local_param.prng_state[0], sizeof( uint64_t ) * 1, &crc32 );
    xrn_crc32( ( uint8_t * ) & local_param.prng_state[1], sizeof( uint64_t ) * 1, &crc32 );
    xrn_crc32( ( uint8_t * ) & local_param.prng_state[2], sizeof( uint64_t ) * 1, &crc32 );
    xrn_crc32( ( uint8_t * ) & local_param.prng_state[3], sizeof( uint64_t ) * 1, &crc32 );

    if ( magic_num != crc32 ) {
        XPRINT_ERR( 694, XERR_MAGIC_MSG );
        return XERR_MAGIC;
    }

    ret = xrn_check_encoding_parameters( local_param );
    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 2185, XERR_GENERAL_MSG );
        return ( ret );
    }

    *param = local_param;

    return final_ret;

}

int xrn_fwrite_encoder( const void *ptr, size_t size, size_t nmemb, FILE * stream, xrn_encoding_param_t * enc_param
 )
{
    XPRINT_DEB(  );

    int ret, i;
    xrn_encoding_tmp_param_t tmp;
    uint8_t *local_ptr;

    if ( ( stream == NULL ) || ( ptr == NULL ) || ( enc_param == NULL ) ) {
        XPRINT_ERR( 118, XERR_NULL_MSG );
        return XERR_NULL;
    }

    local_ptr = ( uint8_t * ) malloc( sizeof( uint8_t ) * size * nmemb );
    if ( local_ptr == NULL ) {
        XPRINT_ERR( 2186, XERR_NULL_MSG );
        return XERR_NULL;
    }

    for ( i = 0; i < size * nmemb; i++ ) {
        local_ptr[i] = ( ( uint8_t * ) ptr )[i];
    }

    ret = xrn_encode( enc_param, local_ptr, local_ptr, size * nmemb, &tmp );

    if ( ret != XSUCCESS ) {

        XRN_FREEN( local_ptr, ( size * nmemb ) );
        XPRINT_ERR( 2187, XERR_GENERAL_MSG );
        return ret;
    }

    ret = ( int ) fwrite( local_ptr, size, nmemb, stream );

    XRN_FREEN( local_ptr, ( size * nmemb ) );

    return ret;

}

int xrn_fread_decoder( void *ptr, size_t size, size_t nmemb, FILE * stream, xrn_encoding_param_t * enc_param
 )
{
    XPRINT_DEB(  );

    int ret;
    int ret_bytes;
    xrn_encoding_tmp_param_t tmp;

    if ( ( stream == NULL ) || ( ptr == NULL ) || ( enc_param == NULL ) ) {
        XPRINT_ERR( 126, XERR_NULL_MSG );
        return XERR_NULL;
    }

    ret_bytes = ( int ) fread( ptr, size, nmemb, stream );
    if ( ret_bytes <= 0 ) {
        return 0;
    }

    ret = xrn_decode( enc_param, ( uint8_t * ) ptr, ( uint8_t * ) ptr, size * nmemb, &tmp );

    if ( ret != XSUCCESS ) {
        XPRINT_ERR( 2188, XERR_GENERAL_MSG );
        return ret;
    }

    return ret_bytes;

}

int xrn_permute_encoding_param_with_file( xrn_encoding_param_t in_encoding_param, FILE * fp,
                                          xrn_encoding_param_t * out_encoding_param
 )
{

    int ret, final_ret, bytes_read;
    xrn_encoding_param_t local_encoding_param;
    uint8_t c;
    xrn_encoding_tmp_param_t tmp;

    final_ret = XSUCCESS;

    if ( ( fp == NULL ) || ( out_encoding_param == NULL ) ) {
        XPRINT_ERR( 766, XERR_NULL_MSG );
        return XERR_NULL;
    }

    bytes_read = 0;
    local_encoding_param = in_encoding_param;

    while ( 1 == fread( &c, sizeof( c ), 1, fp ) ) {

        ret = xrn_encode( &local_encoding_param, &c, &c, 1, &tmp );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 767, XERR_GENERAL_MSG );
            return ret;
        }

        bytes_read++;

    }

    if ( bytes_read < 256 ) {
        XPRINT_ERR( 770, XERR_IO_MSG );
        return XERR_IO;
    }

    *out_encoding_param = local_encoding_param;
    return final_ret;

}

int xrn_permute_encoding_param_with_pass( xrn_encoding_param_t in_encoding_param,
                                          uint8_t password[XRN_ENC_PASS_BUFF_SIZE],
                                          uint16_t password_length, xrn_encoding_param_t * out_encoding_param
 )
{
    XPRINT_DEB(  );

    xrn_encoding_param_t local_param;
    xrn_encoding_tmp_param_t tmp;

    local_param = in_encoding_param;
    int nruns, i, ret, final_ret, padding;
    uint8_t password_buff[XRN_ENC_PASS_BUFF_SIZE + sizeof( local_param.prng_state ) +
                          sizeof( local_param.table )];

    final_ret = XSUCCESS;

    // copy password into the buffer

    padding = 0;

    for ( i = 0; i < XRN_ENC_PASS_BUFF_SIZE; i++ ) {
        if ( i < password_length ) {

            password_buff[i] = password[i];
            padding = 1;

        } else if ( padding == 1 ) {

            password_buff[i] = 128;     // 0x80
            padding = 0;

        } else {

            password_buff[i] = 0;

        }

    }

    // copy counter into the buffer

    for ( i = 0; i < sizeof( local_param.table ); i++ ) {

        password_buff[i + XRN_ENC_PASS_BUFF_SIZE] = ( uint8_t ) ( i % 256 );

    }

    // copy zero into the buffer

    for ( i = 0; i < sizeof( local_param.prng_state ); i++ ) {

        password_buff[i + XRN_ENC_PASS_BUFF_SIZE + ( int ) sizeof( local_param.table )] = 0;

    }

    // encrypt the buffer

    ret =
        xrn_encode( &local_param, password_buff, password_buff,
                    XRN_ENC_PASS_BUFF_SIZE + sizeof( local_param.table ) +
                    sizeof( local_param.prng_state ), &tmp );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 2172, XERR_GENERAL_MSG );
        return ret;
    }

    // re-initialize prng_state

    for ( i = 0; i < sizeof( local_param.prng_state ); i++ ) {

        ( ( uint8_t * ) & local_param.prng_state[0] )[i] =
            password_buff[XRN_ENC_PASS_BUFF_SIZE + ( int ) sizeof( local_param.table ) + i];
    }

    for ( nruns = 1; nruns < 12; nruns++ ) {

        // re-encrypt the buffer

        ret =
            xrn_encode( &local_param, password_buff, password_buff,
                        XRN_ENC_PASS_BUFF_SIZE + sizeof( local_param.table ) +
                        sizeof( local_param.prng_state ), &tmp );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 2173, XERR_GENERAL_MSG );
            return ret;
        }

        // re-re-initialize prng_state

        for ( i = 0; i < sizeof( local_param.prng_state ); i++ ) {

            ( ( uint8_t * ) & local_param.prng_state[0] )[i] =
                password_buff[XRN_ENC_PASS_BUFF_SIZE + ( int ) sizeof( local_param.table ) + i];

        }

    }

    *out_encoding_param = local_param;

    return final_ret;

}

int xrn_check_randomness( uint8_t enc_byte, xrn_encoding_param_t * enc_param, xrn_encoding_tmp_param_t * enc_param_tmp
 )
{
    XPRINT_DEB(  );

    if ( ( enc_param == NULL ) || ( enc_param_tmp == NULL ) ) {
        XPRINT_ERR( 133, XERR_NULL_MSG );
        return XERR_NULL;
    }

    // assumption index = 0;
    // assumption buffer_full = 0;

    enc_param->prob_checks.buffer[enc_param->prob_checks.index] = enc_byte;

    if ( enc_param->prob_checks.buffer_full == 0 ) {

        if ( enc_param->prob_checks.index == XRN_BUFFER_ENC_BIST_SIZE - 1 ) {
            enc_param->prob_checks.buffer_full = 1;

            // initialize all the parameters

            enc_param->prob_checks.count_1 = 0;
            enc_param->prob_checks.count_0 = 0;
            enc_param->prob_checks.count_consecutive_1 = 0;
            enc_param->prob_checks.count_consecutive_0 = 0;
            enc_param->prob_checks.max_consecutive_1 = 0;
            enc_param->prob_checks.max_consecutive_0 = 0;

            // loop through all the bytes in the buffer
            for ( enc_param_tmp->j = 0; enc_param_tmp->j < XRN_BUFFER_ENC_BIST_SIZE; enc_param_tmp->j++ ) {

                enc_param_tmp->byte_tmp = enc_param->prob_checks.buffer[enc_param_tmp->j];

                // loop through all the bits in the bytes
                for ( enc_param_tmp->k = 0; enc_param_tmp->k < 8; enc_param_tmp->k++ ) {

                    // 1 case
                    if ( ( enc_param_tmp->byte_tmp & 0x80 ) == 0x80 ) {

                        enc_param->prob_checks.count_1++;

                        if ( enc_param->prob_checks.count_consecutive_0 >
                             enc_param->prob_checks.max_consecutive_0 ) {
                            enc_param->prob_checks.max_consecutive_0 =
                                enc_param->prob_checks.count_consecutive_0;
                        }

                        enc_param->prob_checks.count_consecutive_0 = 0;
                        enc_param->prob_checks.count_consecutive_1++;

                        // 0 case
                    } else {

                        enc_param->prob_checks.count_0++;

                        if ( enc_param->prob_checks.count_consecutive_1 >
                             enc_param->prob_checks.max_consecutive_1 ) {
                            enc_param->prob_checks.max_consecutive_1 =
                                enc_param->prob_checks.count_consecutive_1;
                        }

                        enc_param->prob_checks.count_consecutive_1 = 0;
                        enc_param->prob_checks.count_consecutive_0++;

                    }

                    enc_param_tmp->byte_tmp = ( uint8_t ) ( enc_param_tmp->byte_tmp << ( uint8_t ) 1 );

                }

                if ( enc_param->prob_checks.count_consecutive_0 > enc_param->prob_checks.max_consecutive_0 ) {
                    enc_param->prob_checks.max_consecutive_0 = enc_param->prob_checks.count_consecutive_0;
                }

                if ( enc_param->prob_checks.count_consecutive_1 > enc_param->prob_checks.max_consecutive_1 ) {
                    enc_param->prob_checks.max_consecutive_1 = enc_param->prob_checks.count_consecutive_1;
                }

            }

            // perform the checks

            if ( enc_param->prob_checks.check_running_error_en == 1 ) {

                if ( enc_param->prob_checks.max_consecutive_0 >=
                     enc_param->prob_checks.max_consecutives_01s_threshold_error ) {

                    XPRINT_ERR( 2192, XERR_PROB_ENC_C0_MSG );
                    return ( XERR_PROB_ENC_C0 );

                } else if ( enc_param->prob_checks.max_consecutive_1 >=
                            enc_param->prob_checks.max_consecutives_01s_threshold_error ) {

                    XPRINT_ERR( 2193, XERR_PROB_ENC_C1_MSG );
                    return ( XERR_PROB_ENC_C1 );

                } else if ( enc_param->prob_checks.max_consecutive_0 >=
                            enc_param->prob_checks.max_consecutives_01s_threshold_warning ) {

                    XPRINT_WAR( XWAR_PROB_ENC_C0_MSG, XWAR_PROB_ENC_C0 );
                    return ( int ) ( XWAR_PROB_ENC_C0 );

                } else if ( enc_param->prob_checks.max_consecutive_1 >=
                            enc_param->prob_checks.max_consecutives_01s_threshold_warning ) {

                    XPRINT_WAR( XWAR_PROB_ENC_C1_MSG, XWAR_PROB_ENC_C1 );
                    return ( int ) ( XWAR_PROB_ENC_C1 );

                }

            }

            if ( enc_param->prob_checks.check_disparity_error_en == 1 ) {

                if ( enc_param->prob_checks.count_0 >=
                     enc_param->prob_checks.max_number_of_01s_threshold_error ) {

                    XPRINT_ERR( 2194, XERR_PROB_ENC_0_MSG );
                    return ( XERR_PROB_ENC_0 );

                } else if ( enc_param->prob_checks.count_1 >=
                            enc_param->prob_checks.max_number_of_01s_threshold_error ) {

                    XPRINT_ERR( 2195, XERR_PROB_ENC_1_MSG );
                    return ( XERR_PROB_ENC_1 );

                } else if ( enc_param->prob_checks.count_0 >=
                            enc_param->prob_checks.max_number_of_01s_threshold_warning ) {

                    XPRINT_WAR( XWAR_PROB_ENC_0_MSG, XWAR_PROB_ENC_0 );
                    return ( int ) ( XWAR_PROB_ENC_0 );

                } else if ( enc_param->prob_checks.count_1 >=
                            enc_param->prob_checks.max_number_of_01s_threshold_warning ) {

                    XPRINT_WAR( XWAR_PROB_ENC_1_MSG, XWAR_PROB_ENC_1 );
                    return ( int ) ( XWAR_PROB_ENC_1 );

                }

            }

        }

    } else {

        // remove oldest progress

        enc_param_tmp->byte_tmp =
            enc_param->prob_checks.buffer[( enc_param->prob_checks.index + 1 ) % XRN_BUFFER_ENC_BIST_SIZE];

        // loop through all the bits in the bytes
        for ( enc_param_tmp->k = 0; enc_param_tmp->k < 8; enc_param_tmp->k++ ) {

            // 1 case
            if ( ( enc_param_tmp->byte_tmp & 0x80 ) == 0x80 ) {

                enc_param->prob_checks.count_1--;

                // 0 case
            } else {

                enc_param->prob_checks.count_0--;

            }

            enc_param_tmp->byte_tmp = ( uint8_t ) ( enc_param_tmp->byte_tmp << ( uint8_t ) 1 );

        }

        // add newest progress

        enc_param_tmp->byte_tmp = enc_param->prob_checks.buffer[enc_param->prob_checks.index];

        // loop through all the bits in the bytes
        for ( enc_param_tmp->k = 0; enc_param_tmp->k < 8; enc_param_tmp->k++ ) {

            // 1 case
            if ( ( enc_param_tmp->byte_tmp & 0x80 ) == 0x80 ) {

                enc_param->prob_checks.count_1++;

                if ( enc_param->prob_checks.count_consecutive_0 > enc_param->prob_checks.max_consecutive_0 ) {
                    enc_param->prob_checks.max_consecutive_0 = enc_param->prob_checks.count_consecutive_0;
                }

                enc_param->prob_checks.count_consecutive_0 = 0;
                enc_param->prob_checks.count_consecutive_1++;

                // 0 case
            } else {

                enc_param->prob_checks.count_0++;

                if ( enc_param->prob_checks.count_consecutive_1 > enc_param->prob_checks.max_consecutive_1 ) {
                    enc_param->prob_checks.max_consecutive_1 = enc_param->prob_checks.count_consecutive_1;
                }

                enc_param->prob_checks.count_consecutive_1 = 0;
                enc_param->prob_checks.count_consecutive_0++;

            }

            enc_param_tmp->byte_tmp = ( uint8_t ) ( enc_param_tmp->byte_tmp << ( uint8_t ) 1 );

        }

        if ( enc_param->prob_checks.count_consecutive_0 > enc_param->prob_checks.max_consecutive_0 ) {
            enc_param->prob_checks.max_consecutive_0 = enc_param->prob_checks.count_consecutive_0;
        }

        if ( enc_param->prob_checks.count_consecutive_1 > enc_param->prob_checks.max_consecutive_1 ) {
            enc_param->prob_checks.max_consecutive_1 = enc_param->prob_checks.count_consecutive_1;
        }

        // perform the checks

        if ( enc_param->prob_checks.check_running_error_en == 1 ) {

            if ( enc_param->prob_checks.max_consecutive_0 >=
                 enc_param->prob_checks.max_consecutives_01s_threshold_error ) {

                XPRINT_ERR( 2196, XERR_PROB_ENC_C0_MSG );
                return ( XERR_PROB_ENC_C0 );

            } else if ( enc_param->prob_checks.max_consecutive_1 >=
                        enc_param->prob_checks.max_consecutives_01s_threshold_error ) {

                XPRINT_ERR( 2197, XERR_PROB_ENC_C1_MSG );
                return ( XERR_PROB_ENC_C1 );

            } else if ( enc_param->prob_checks.max_consecutive_0 >=
                        enc_param->prob_checks.max_consecutives_01s_threshold_warning ) {

                XPRINT_WAR( XWAR_PROB_ENC_C0_MSG, XWAR_PROB_ENC_C0 );
                return ( int ) ( XWAR_PROB_ENC_C0 );

            } else if ( enc_param->prob_checks.max_consecutive_1 >=
                        enc_param->prob_checks.max_consecutives_01s_threshold_warning ) {

                XPRINT_WAR( XWAR_PROB_ENC_C1_MSG, XWAR_PROB_ENC_C1 );
                return ( int ) XWAR_PROB_ENC_C1;

            }

        }

        if ( enc_param->prob_checks.check_disparity_error_en == 1 ) {

            if ( enc_param->prob_checks.count_0 >= enc_param->prob_checks.max_number_of_01s_threshold_error ) {

                XPRINT_ERR( 2198, XERR_PROB_ENC_0_MSG );
                return ( XERR_PROB_ENC_0 );

            } else if ( enc_param->prob_checks.count_1 >=
                        enc_param->prob_checks.max_number_of_01s_threshold_error ) {

                XPRINT_ERR( 2199, XERR_PROB_ENC_1_MSG );
                return ( XERR_PROB_ENC_1 );

            } else if ( enc_param->prob_checks.count_0 >=
                        enc_param->prob_checks.max_number_of_01s_threshold_warning ) {

                XPRINT_WAR( XWAR_PROB_ENC_0_MSG, XWAR_PROB_ENC_0 );
                return ( int ) ( XWAR_PROB_ENC_0 );

            } else if ( enc_param->prob_checks.count_1 >=
                        enc_param->prob_checks.max_number_of_01s_threshold_warning ) {

                XPRINT_WAR( XWAR_PROB_ENC_1_MSG, XWAR_PROB_ENC_1 );
                return ( int ) ( XWAR_PROB_ENC_1 );

            }

        }

    }

    enc_param->prob_checks.index =
        ( uint8_t ) ( ( enc_param->prob_checks.index + 1 ) % XRN_BUFFER_ENC_BIST_SIZE );

    return XSUCCESS;
}

int xrn_initialize_encoding_settings( xrn_encoding_settings_t * encoding_settings
 )
{
    XPRINT_DEB(  );
    xrn_encoding_settings_t encoding_settings_local;
    int i;

    if ( encoding_settings == NULL ) {
        XPRINT_ERR( 2200, XERR_NULL_MSG );
        return XERR_NULL;
    }

    for ( i = 0; i < sizeof( encoding_settings_local ); i++ ) {
        ( ( uint8_t * ) & encoding_settings_local )[i] = 0;
    }

    encoding_settings_local.check_mode = xrn_automatic;
    encoding_settings_local.mode = std_parameters;
    encoding_settings_local.check_running_error_en = 1;
    encoding_settings_local.check_disparity_error_en = 1;
    encoding_settings_local.initialization_file_fp = NULL;
    encoding_settings_local.max_consecutives_01s_threshold_error = XRN_ENC_MAX_CONS_01_ERR_TH;
    encoding_settings_local.max_consecutives_01s_threshold_warning = XRN_ENC_MAX_CONS_01_WAR_TH;
    encoding_settings_local.max_number_of_01s_threshold_error = XRN_ENC_MAX_AVG_01_ERR_TH;
    encoding_settings_local.max_number_of_01s_threshold_warning = XRN_ENC_MAX_AVG_01_WAR_TH;

    *encoding_settings = encoding_settings_local;

    return XSUCCESS;

}

